package com.gdsz.libbasic.view.adapter

import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.gdsz.libbasic.extensions.getViewBinding

import java.util.LinkedList

abstract class BaseRecyclerAdapter<T, VB : ViewDataBinding> :
    RecyclerView.Adapter<BindViewHolder<VB>>() {
    private var mData: List<T> = mutableListOf()
    protected lateinit var context:Context
    fun setData(data: List<T>?) {

        data?.let {
            val result = DiffUtil.calculateDiff(object : DiffUtil.Callback() {
                override fun getOldListSize(): Int {
                    return mData.size
                }

                override fun getNewListSize(): Int {
                    return it.size
                }

                override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
                    val oldData: T = mData[oldItemPosition]
                    val newData: T = it[newItemPosition]
                    return this@BaseRecyclerAdapter.areItemsTheSame(oldData, newData)
                }

                override fun areContentsTheSame(
                    oldItemPosition: Int,
                    newItemPosition: Int
                ): Boolean {
                    val oldData: T = mData[oldItemPosition]
                    val newData: T = it[newItemPosition]
                    return this@BaseRecyclerAdapter.areItemContentsTheSame(
                        oldData,
                        newData,
                        oldItemPosition,
                        newItemPosition
                    )
                }
            })
            mData = data
            result.dispatchUpdatesTo(this)
        } ?: let {
            mData = mutableListOf()
            notifyItemRangeChanged(0, mData.size)
        }

    }

    fun addData(data: List<T>?, position: Int? = null) {
        if (!data.isNullOrEmpty()) {
            with(LinkedList(mData)) {
                position?.let {
                    val startPosition = when {
                        it < 0 -> 0
                        it >= size -> size
                        else -> it
                    }
                    addAll(startPosition, data)
                } ?: addAll(data)
                setData(this)

            }
        }
    }

    fun addData(data: T?, position: Int? = null) {
        data?.let {

            with(LinkedList(mData)) {
                position?.let {
                    val startPosition = when {
                        it < 0 -> 0
                        it >= size -> size
                        else -> it
                    }
                    add(startPosition, data)
                } ?: add(data)
                setData(this)
            }
        }
    }

    fun removeIndex(position: Int) {
        with(LinkedList(mData)) {
            removeAt(position)
            setData(this)
        }
    }


    fun removeData(data: T?) {
        with(LinkedList(mData)) {
            remove(data)
            setData(this)
        }
    }

    /**
     * 判断item中的内容是否相同
     * @param oldItem T
     * @param newItem T
     * @param oldItemPosition Int
     * @param newItemPosition Int
     * @return Boolean
     */
    protected open fun areItemContentsTheSame(
        oldItem: T,
        newItem: T,
        oldItemPosition: Int,
        newItemPosition: Int
    ): Boolean {
        return oldItem == newItem
    }

    /**
     * 判断item是否相同  一般是按照Id来判断
     * @param oldItem T
     * @param newItem T
     * @return Boolean
     */
    protected open fun areItemsTheSame(oldItem: T, newItem: T): Boolean {
        return oldItem == newItem
    }

    fun getData(): List<T> {
        return mData
    }

   open fun getItem(position: Int): T {
        return mData[position]
    }

    fun getActualPosition(data: T): Int {
        return mData.indexOf(data)
    }

    override fun getItemCount(): Int {
        return mData.size
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindViewHolder<VB> {
        context = parent.context
        return with(getViewBinding<VB>(LayoutInflater.from(parent.context), parent, 1)) {
            setListener()
            BindViewHolder(this)
        }
    }

    override fun onBindViewHolder(holder: BindViewHolder<VB>, position: Int) {
        with(holder.binding) {
            onBindViewHolder(getItem(position), position)
            executePendingBindings()
        }
    }

    open fun VB.setListener() {}

    abstract fun VB.onBindViewHolder(itemData: T, position: Int)


    protected var onItemClickListener: ((type: Int, position: Int, data: T) -> Unit)? = null


    fun onItemClickListener(block: (type: Int, position: Int, data: T) -> Unit) {
        onItemClickListener = block
    }


}